/**
* Title: MyPriorityQueueKPlus1ElementTest.java
* Description: Tests the grow(int) method from MyPriorityQueue class using equivalence partitioning analysis
* 				for queue with k elements (Induction K+1)
* Copyright: Copyright (c) 2011
* Company: University of Texas at Arlington
* @author: Duy Nguyen and Shreya Mamadapur
* @version 1.0
*/




import java.util.Random;

import junit.framework.TestCase;
import junitx.util.PrivateAccessor;

import org.junit.Before;
import org.junit.Test;

public class MyPriorityQueueKPlus1ElementTest extends TestCase{
	private static MyPriorityQueue mpq; 
	private MyComparator comparator;
	static IntegerElement e;
	static Object[] o, o1;
	static int exceptionThrown ;
	int k,queueLength, capacity;
	int defaultCapacity = 0, firstDecisiveCapacity = 64;
	private Random random = null;
		
	
	
	@Before
	public void setUp() throws Exception {
		e = new IntegerElement(0);
		
		// obtain the default capacity by accessing the private variable called DEFAULT_INITIAL_CAPACITY
		defaultCapacity = Integer.parseInt(PrivateAccessor.getField(
				MyPriorityQueue.class, "DEFAULT_INITIAL_CAPACITY").toString());
		random = new Random();
		comparator = new MyComparator();
		
	}
	
	
	
	/**
	 * Test 1 - On a k+1 element queue, 
	 * 			test the grow method by passing in a negative desired capacity, an exception should be thrown
	 * 
	 */
	@Test
	public void testGrowWithNegativeMinCapacity() {
		boolean exceptionThrown = false;
		
		mpq = new MyPriorityQueue(1,comparator);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(0,queueLength);
		
		// Insert one random element into the queue
		
		e.setValue(random.nextInt(100));
		mpq.add(e);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(1,queueLength);
		
		
		// Generate random k elements and add them to the queue, to get a k+1 element queue		
		k = random.nextInt(50);
			
		for (int i = 1; i <= k; ++i){
	      
			e.setValue(random.nextInt(100));
			mpq.add(e);
	      
	    }
		
		o1 = mpq.toArray();

		queueLength = o1.length;
		
		assertEquals(k+1,queueLength);
		
			try {
				PrivateAccessor.invoke(mpq, "grow", new Class[]{int.class}, new Object[]{new Integer( -10 )} );
			} 
			catch (java.lang.OutOfMemoryError e) {
				exceptionThrown = true;
			}
			catch (Throwable e) {}
		 

		assertTrue(exceptionThrown);
		}
	
	/**
	 * Test 2 - On a k+1 element queue, 
	 * 			test the grow method by passing in a 0 desired capacity,
	 * 			the new capacity should be the values as follows: if less than 11, then 11; 
	 * 			if between 11 and 24, then 24; if between 24 and 50, then 50;
	 * 			if between 50 and 64, then 64
	 * 
	 */
	@Test
	public void testGrowWithZeroMinCapacityAndDefaultInitCap() {
			
		
		mpq = new MyPriorityQueue(1,comparator);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(0,queueLength);
		
		// Insert one random element into the queue
				
		e.setValue(random.nextInt(100));
		mpq.add(e);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(1,queueLength);
		
		
		// Generate random k elements and add them to the queue, to get a k+1 element queue
		
		k = random.nextInt(50);
			
		for (int i = 1; i <= k; ++i){
	      
			e.setValue(random.nextInt(100));
			mpq.add(e);
	      
	    }
		
		o1 = mpq.toArray();

		queueLength = o1.length;
		
		assertEquals(k+1,queueLength);

		try {
				
				o = (Object[]) PrivateAccessor.getField(mpq, "queue" );
				
				capacity = o.length;
				
				
				if ( (k+1) <= defaultCapacity)
					assertEquals(defaultCapacity,capacity);
				else if ( (k+1) > defaultCapacity && (k+1) <= ((defaultCapacity+1)*2))
					assertEquals((defaultCapacity+1)*2,capacity);
				else if ( (k+1) > (defaultCapacity+1)*2 && (k+1) <= (((defaultCapacity+1)*2)+1)*2)
					assertEquals((((defaultCapacity+1)*2)+1)*2,capacity);
				else if ( (k+1) > (((defaultCapacity+1)*2)+1)*2 && (k+1) < firstDecisiveCapacity)
					assertEquals(firstDecisiveCapacity,capacity);
			} 
			catch (NoSuchFieldException e1) {}
			catch (Throwable e) {}
			
			
	}	

	/**
	 * Test 3 - On a k+1 element queue, 
	 * 			test the grow method by passing in a positive desired capacity,
	 * 			the new capacity should be the values as follows: if less than 11, then 11; 
	 * 			if between 11 and 24, then 24; if between 24 and 50, then 50;
	 * 			if between 50 and 64, then 64
	 * 
	 */
	@Test
	public void testGrowWithPositiveMinCapacityAndDefaultInitCap() {
				
		mpq = new MyPriorityQueue(1,comparator);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(0,queueLength);
		
		// Insert one random element into the queue
		e.setValue(random.nextInt(100));
		mpq.add(e);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(1,queueLength);
		
		
		// Generate random k elements and add them to the queue, to get a k+1 element queue
		
		k = random.nextInt(50);
			
		for (int i = 1; i <= k; ++i){
	      
			e.setValue(random.nextInt(100));
			mpq.add(e);
	      
	    }
		
		o1 = mpq.toArray();

		queueLength = o1.length;
		
		assertEquals(k+1,queueLength);

			
			try {
				
				o = (Object[]) PrivateAccessor.getField(mpq, "queue" );
				capacity = o.length;				
				
				if ( (k+1) <= defaultCapacity)
					assertEquals(defaultCapacity,capacity);
				else if ( (k+1) > defaultCapacity && (k+1) <= ((defaultCapacity+1)*2))
					assertEquals((defaultCapacity+1)*2,capacity);
				else if ( (k+1) > (defaultCapacity+1)*2 && (k+1) <= (((defaultCapacity+1)*2)+1)*2)
					assertEquals((((defaultCapacity+1)*2)+1)*2,capacity);
				else if ( (k+1) > (((defaultCapacity+1)*2)+1)*2 && (k+1) < firstDecisiveCapacity)
					assertEquals(firstDecisiveCapacity,capacity);
			} 
			catch (NoSuchFieldException e1) {}
			catch (Throwable e) {}
			
	}	

	/**
	 * Test 4- On a k+1 element queue, 
	 * 			test the grow method testing to see if the new capacity is as per conditions below 
	 * 
	 */
	@Test
	public void testGrowWithPositiveMinCapacityAndInitCapGreaterThan64() {
			
		
		
		int inputCap = 64 + random.nextInt(100);
		mpq = new MyPriorityQueue(inputCap,comparator);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(0,queueLength);
		
		// Insert one random element into the queue
		e.setValue(random.nextInt(100));
		mpq.add(e);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(1,queueLength);
		
		
		// Generate random k elements and add them to the queue, to get a k+1 element queue
		
		k = random.nextInt(50);
			
		for (int i = 1; i <= k; ++i){
	      
			e.setValue(random.nextInt(100));
			mpq.add(e);
	      
	    }
		
		o1 = mpq.toArray();

		queueLength = o1.length;
		
		assertEquals(k+1,queueLength);
				
				
			try {
				
				o = (Object[]) PrivateAccessor.getField(mpq, "queue" );
				
				capacity = o.length;		
				if ( k <= (defaultCapacity+1))
					assertEquals((defaultCapacity+1),capacity);
				else if ( (k > (defaultCapacity+1)) && (k <= ((defaultCapacity+1)/2)*3))
					assertEquals(((defaultCapacity+1)/2)*3, capacity);
				else if (k > ((defaultCapacity+1)/2)*3)
					assertEquals(((((defaultCapacity+1)/2)*3)/2)*3, capacity);
			} 
			catch (NoSuchFieldException e1) {}
			catch (Throwable e) {}
			
			
	}	
	
	/**
	 * On a k+1 element queue, 
	 * 			test the grow method testing to see if the new capacity 
	 * 			is the same as the min capacity when the desired capacity is less than the initial capacity
	 * 
	 */
	@Test
	public void testGrowForNewCapBeingSetToMinCap() {
			
				
		mpq = new MyPriorityQueue(64,comparator);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(0,queueLength);
		
		// Insert one random element into the queue
			
		e.setValue(random.nextInt(100));
		mpq.add(e);
		
		o1 = mpq.toArray();
		
		queueLength = o1.length;
		
		assertEquals(1,queueLength);
		
		
		// Generate random k elements and add them to the queue, to get a k+1 element queue
		
		k = random.nextInt(50);
			
		for (int i = 1; i <= k; ++i){
	      
			e.setValue(random.nextInt(100));
			mpq.add(e);
	      
	    }
		
		o1 = mpq.toArray();

		queueLength = o1.length;
		
		assertEquals(k+1,queueLength);
		

		int inputCapacity = 64 + random.nextInt(2000);
		
				
			try {
			
				PrivateAccessor.invoke(mpq, "grow", new Class[]{int.class}, new Object[]{new Integer( inputCapacity )} );
			
				o = (Object[]) PrivateAccessor.getField(mpq, "queue" );
				
				capacity = o.length;		
				assertEquals(inputCapacity,capacity);
			} 
			catch (NoSuchFieldException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			catch (Throwable e) {
				// TODO Auto-generated catch block
		
				e.printStackTrace();
			}
			
			
	}
	
	

}